package com.psmz.iwi.docanalyzer.core.classification.business;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.classification.ClassificationResult;
import org.apache.lucene.classification.SimpleNaiveBayesClassifier;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.SlowCompositeReaderWrapper;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;

import com.psmz.iwi.docanalyzer.core.document.entities.Document;
import com.psmz.iwi.docanalyzer.core.settings.ApplicationSettings;

/**
 * Klasyfikacja dokumentow zgodnie z naiwnym klasyfikatorem bayesa.
 * 
 * @author pszwarc
 * 
 */
public class ClassificationService {

	private ApplicationSettings settings;
	/**
	 * Bayes classifier - staly.
	 */
	private static final SimpleNaiveBayesClassifier BAYES_CLASSIFIER = new SimpleNaiveBayesClassifier();

	public ClassificationService(ApplicationSettings settings) {
		this.settings = settings;
	}

	/**
	 * Przeprowadza operacje trenowania klasyfikatora.
	 * 
	 * @throws ClassificationServiceException
	 *             Wyrzucany w przypadku bledu trenowania.
	 */
	public void train() throws ClassificationServiceException {
		// trenujemy klasyfikator na podstawie indeksu
		AtomicReader reader = null;
		try {
			reader = openIndex();
			BAYES_CLASSIFIER.train(reader, Document.CONTENT_FIELD,
					Document.DOCUMENT_CLASS_FIELD, new SimpleAnalyzer(
							Version.LUCENE_45));
		} catch (IOException e) {
			System.err.println(e.toString());
			throw new ClassificationServiceException("Blad wejscia/wyjscia", e);
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				System.err.println(e.toString());
			}
		}
	}

	/**
	 * Dokonuje klasyfikacji pojedynczego dokumentu.
	 * 
	 * @param document
	 *            Dokument, ktory ma byc klasyfikowany.
	 * @return Nazwa klasy, do jakiej zostala przypisana zawartosc.
	 * @throws ClassificationServiceException
	 *             Wyrzucany w przypadku bledu klasyfikacji.
	 */
	public String classify(String content)
			throws ClassificationServiceException {
		try {
			ClassificationResult<BytesRef> result = BAYES_CLASSIFIER
					.assignClass(content);
			return result.getAssignedClass().utf8ToString();
		} catch (IOException e) {
			System.err.println();
			throw new ClassificationServiceException("Blad wejscia/wyjscia", e);
		}
	}

	private AtomicReader openIndex() throws IOException {
		FSDirectory fsDirectory = FSDirectory.open(new File(settings
				.getIndexPath()));
		DirectoryReader directoryReader = DirectoryReader.open(fsDirectory);
		return SlowCompositeReaderWrapper.wrap(directoryReader);
	}

}
